package cn.openea.perpartner.payment.web.coupon.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.openea.perpartner.common.core.utils.IdUtil;
import cn.openea.perpartner.payment.rabbit.domain.BusinessDto;
import cn.openea.perpartner.payment.rabbit.service.impl.PublisherService;
import cn.openea.perpartner.payment.web.coupon.entity.Coupon;
import cn.openea.perpartner.payment.web.coupon.entity.CouponBatch;
import cn.openea.perpartner.payment.web.coupon.entity.dto.CouponDto;
import cn.openea.perpartner.payment.web.coupon.mapper.CouponBatchMapper;
import cn.openea.perpartner.payment.web.coupon.mapper.CouponMapper;
import cn.openea.perpartner.payment.web.coupon.service.ICouponBatchService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * 平台优惠券表(Coupon)表服务实现类
 *
 * @author Weird077
 * @since 2023-04-14 14:29:49
 */
@Slf4j
@Service("couponBatchService")
public class CouponBatchServiceImpl extends ServiceImpl<CouponBatchMapper, CouponBatch> implements ICouponBatchService {
    @Autowired
    private CouponMapper couponMapper;

    @Autowired
    private PublisherService publisherService;
    private static final String BATCH_NAME = "玫丽生活购物通用券";

    @Override
    public List<CouponBatch> selectCouponList(CouponBatch coupon) {
        LambdaQueryWrapper<CouponBatch> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(coupon.getCouponName())) {
            wrapper.like(CouponBatch::getCouponName, coupon.getCouponName());
        }
        if (StrUtil.isNotBlank(coupon.getCouponType())) {
            wrapper.eq(CouponBatch::getCouponType, coupon.getCouponType());
        }
        if (StrUtil.isNotBlank(coupon.getAllowStack())) {
            wrapper.eq(CouponBatch::getAllowStack, coupon.getAllowStack());
        }
        if (StrUtil.isNotBlank(coupon.getUseScope())) {
            wrapper.eq(CouponBatch::getUseScope, coupon.getUseScope());
        }
        wrapper.orderByDesc(CouponBatch::getCreateTime);
        return list(wrapper);
    }

    @Override
    public boolean checkCouponUsed(long recordId) {
        return couponMapper.selectCount(Wrappers.<Coupon>lambdaQuery()
                .eq(Coupon::getId, recordId)
                .eq(Coupon::getStatus, "0")) == 0;
    }

    @Override
    public boolean checkCouponExist(Long couponId) {

        return count(Wrappers.<CouponBatch>lambdaQuery().eq(CouponBatch::getCouponId, couponId)) > 0;
    }

    @Override
    public boolean checkCouponCap(Long couponId) {
        CouponBatch coupon = getById(couponId);
        int couponCap = coupon.getCouponNum();
        if (couponCap == 0) {
            return true;
        }
        long userCouponCount = couponMapper.selectCount(Wrappers.<Coupon>lambdaQuery()
                .eq(Coupon::getCouponId, couponId));
        return couponCap > userCouponCount;
    }

    @Override
    public boolean checkUserCouponCap(String userId, Long couponId) {
        CouponBatch coupon = getById(couponId);
        int drawNum = coupon.getDrawNum();
        if (drawNum == 0) {
            return true;
        }
        long userCouponCount = couponMapper.selectCount(Wrappers.<Coupon>lambdaQuery()
                .eq(Coupon::getCouponId, couponId)
                .eq(Coupon::getUserId, userId));
        return drawNum > userCouponCount;
    }

    @Override
    public boolean createAndIssueCoupon(CouponDto couponDto) {
        Long batchId = couponDto.getBatchId();
        LambdaQueryWrapper<CouponBatch> wrapper = new LambdaQueryWrapper<>();
        //1、若batchId不为空，则根据batchId和券额查询优惠券
        if (ObjectUtil.isNotNull(batchId)) {
            wrapper.eq(CouponBatch::getBatchId, batchId);
        }
        //2、若batchId为空，则根据名称和券额查询优惠券
        else {
            wrapper.eq(CouponBatch::getBatchName, BATCH_NAME);
        }
        wrapper.eq(CouponBatch::getCouponAmount, couponDto.getCouponAmount());
        //3、查询优惠券,若不存在则创建优惠券
        CouponBatch couponBatch = getOne(wrapper);
        if (BeanUtil.isEmpty(couponBatch)) {
            couponBatch = new CouponBatch();
            couponBatch.setCouponAmount(couponDto.getCouponAmount());
            //4、若batchId为空，则创建平台优惠券
            if (ObjectUtil.isNull(batchId)) {
                couponBatch.setBatchId(IdUtil.nextId());
                couponBatch.setBatchName(BATCH_NAME);
                couponBatch.setCouponName(BATCH_NAME);
            }
            //5、若batchId不为空，则创建商家优惠券
            else {
                couponBatch.setBatchId(couponDto.getBatchId());
                couponBatch.setBatchName(couponDto.getCouponName());
                couponBatch.setCouponName(couponDto.getCouponName());
            }
            //6、设置优惠券使用范围
            if (StrUtil.isNotBlank(couponDto.getUseScope())) {
                couponBatch.setUseScope(couponDto.getUseScope());
            }
            saveOrUpdate(couponBatch);
        }
        else {
            BigDecimal oldAmount = couponBatch.getCouponAmount();
            BigDecimal newAmount = couponDto.getCouponAmount();
            //7、若券额发生变化，则创建新优惠券
            if (oldAmount.compareTo(newAmount) != 0) {
                couponBatch = new CouponBatch();
                couponBatch.setCouponAmount(newAmount);
                if (ObjectUtil.isNull(batchId)) {
                    couponBatch.setBatchId(IdUtil.nextId());
                    couponBatch.setBatchName(BATCH_NAME);
                    couponBatch.setCouponName(BATCH_NAME);
                } else {
                    couponBatch.setBatchId(couponDto.getBatchId());
                    couponBatch.setBatchName(couponDto.getCouponName());
                    couponBatch.setCouponName(couponDto.getCouponName());
                }
                //8、设置优惠券使用范围
                if (StrUtil.isNotBlank(couponDto.getUseScope())) {
                    couponBatch.setUseScope(couponDto.getUseScope());
                }
                saveOrUpdate(couponBatch);
            }
        }
        //9、给用户发放优惠券
        int aging = Optional.ofNullable(couponDto.getAging()).orElse(7);
        DateTime validTime = DateUtil.offsetDay(new Date(), aging);
        Coupon coupon = Coupon.builder()
                .userId(couponDto.getUserId())
                .couponId(couponBatch.getCouponId())
                .batchId(couponBatch.getBatchId())
                .validateTime(DateUtil.formatDate(validTime).concat(" 23:59:59"))
                .build();
        boolean result = couponMapper.insert(coupon) > 0;
        //10、设置定时任务，优惠券到期自动失效
        DateTime now = DateUtil.date();
        DateTime nextTime = DateUtil.offsetDay(now, aging);
        long delayTime = DateUtil.betweenMs(now, nextTime);
        BusinessDto business = BusinessDto.builder()
                .beanName("couponService")
                .delayTime(delayTime)
                .params(BeanUtil.toBean(coupon, JSONObject.class))
                .build();
        publisherService.execute(business);
        return result;
    }

}

